#pragma once

#include "znx_defs.h"
#include "znx_rbtree.h"
#include "znx_queue.h"
#include "znx_log.h"
#include "znx_thread_base.h"


/**
 * Notice: znx_slru
 * znx does not have concurrency security and reference counting management,
 * which needs to be done by the caller.
 * 
 * Usually when using interfaces such as get/put, slru needs to be locked.
 * The data obtained through get usually requires its reference count +1,
 * and its reference count -1 after use,
 * when the reference count becomes 0, the data needs to be released.
 */


typedef size_t (*znx_slru_item_size_get_handler_t)(void *data);

typedef void (*znx_slru_item_free_handler_t)(void *data);

typedef int (*znx_slru_item_cmp_handler_t)(void *data_a, void *data_b);


typedef struct {
    int64_t                                 nlist;
    int64_t                                 max_item;
    int64_t                                 max_bytes;
    znx_slru_item_size_get_handler_t        size_get_handler;
    znx_slru_item_free_handler_t            free_handler;
    znx_slru_item_cmp_handler_t             cmp_handler;

    znx_queue_t                             *lists;
    int64_t                                 *lists_bytes;
    int64_t                                 *lists_n;

    znx_rbtree_t                            tree;
    znx_rbtree_node_t                       sentinel;
} znx_slru_t;


znx_slru_t *znx_slru_create(
    int64_t                             nlist,
    int64_t                             max_item,
    int64_t                             max_bytes,
    znx_slru_item_size_get_handler_t    size_get_handler,
    znx_slru_item_free_handler_t        free_handler,
    znx_slru_item_cmp_handler_t         cmp_handler);


void znx_slru_destroy(znx_slru_t *slru);

// if not found, return false
znx_bool_t znx_slru_get(znx_slru_t *slru, void *target, void **data);

void znx_slru_put(znx_slru_t *slru, void *data);

// remove and free cache item
znx_bool_t znx_slru_remove(znx_slru_t *slru, void *target);

// will not increase the heat of the object
znx_bool_t znx_slru_ge(znx_slru_t *slru, void *target, void **data);

// will not increase the heat of the object
znx_bool_t znx_slru_le(znx_slru_t *slru, void *target, void **data);
